import wx
import wx.lib.scrolledpanel as sp
import functions

class PanelDays(sp.ScrolledPanel):
    _pnldays = None
    
    def __init__(self, parent, calevents = dict()):
        sp.ScrolledPanel.__init__(self, parent)

        vbox = wx.BoxSizer(wx.VERTICAL)
        self._pnldays = _PanelDays(self, calevents)
        vbox.Add(self._pnldays, 0, wx.EXPAND | wx.ALL, 0)
        self.SetSizer(vbox)
        self.SetAutoLayout(1)
        self.SetupScrolling(False, True, -1, 1)
       
        self.Bind(wx.EVT_SIZE, self.OnSize)
        
    def OnSize(self, event):
        self.Sizer.GetItem(0).GetWindow().SetSize(self.ClientSize)
        self.Sizer.GetItem(0).GetWindow().Refresh()

class _PanelEvt(wx.Panel):
    def __init__(self, parent, calevent):
        self.oldPos = None
        self.isResizing = False
        self.resizeOutside = False
        self.resizeFromTop = False
        self.calevent = calevent
                
        wx.Panel.__init__(self, parent)
#        self.SetBackgroundColour(color)
        
        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.Bind(wx.EVT_MOTION, self.OnMotion)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        
        self.bgcolor = wx.Color()
        self.bgcolor.SetFromName(calevent['col'])
        
        self.startTime = functions.rfc3339.ToWxDateTime(calevent['evt'].extension_elements[5].attributes['startTime'])
        self.endTime = functions.rfc3339.ToWxDateTime(calevent['evt'].extension_elements[5].attributes['endTime'])
        self.SetEvtTime()

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        rect = self.GetClientRect()
        dc.SetPen(wx.Pen(self.bgcolor))
        dc.SetBrush(wx.Brush(functions.Brighter(self.bgcolor)))
        dc.DrawRectangleRect(rect)
        rect.SetHeight(12)
        dc.SetBrush(wx.Brush(self.bgcolor))
        dc.DrawRectangleRect(rect)
        
        font = self.GetFont()
        font.SetPointSize(7)
        dc.SetTextForeground(wx.Color(255,255,255))
        dc.SetFont(font)
        dc.DrawText(self.startTime.Format('%H:%M') + ' - ' + self.endTime.Format('%H:%M'),2,0)

        font.SetPointSize(9)
        dc.SetFont(font)
        dc.DrawText(self.calevent['evt'].title.text,2,13)

    def OnEraseBackground(self, event):
        pass
        
    def OnLeftDown(self, event):
        self.oldPos = event.GetPosition()
        self.CaptureMouse()
        self.Parent.tooltip.Show(True)
        
    def OnMotion(self, event): 
        pos = event.GetPosition()
        if not event.Dragging() or not event.LeftIsDown():
            if pos.y < 3:
                self.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS))
                self.isResizing = True
                self.resizeFromTop = True
            elif pos.y > self.Size.y - 4:
                self.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS))
                self.isResizing = True
                self.resizeFromTop = False
            else:
                self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
                self.isResizing = False
            event.Skip()
            return
        
        if self.isResizing:
            if self.resizeFromTop:
                newpos = wx.Point(-1, self.GetPosition().y + pos.y - self.oldPos.y)
                newheight = self.Size.y - pos.y + self.oldPos.y
                
                if newpos.y < self.Parent.titleHeight or newheight <= 15:
                    self.resizeOutside = True
                else:
                    self.resizeOutside = False
            else:
                newpos = self.GetPosition()
                newheight = self.Size.y + pos.y - self.oldPos.y
                self.oldPos = pos

                if newpos.y + newheight >= self.Parent.Size.y +1 or newheight <= 15:
                    self.resizeOutside = True
                else:
                    self.resizeOutside = False
            
            if not self.resizeOutside:
                self.Move(newpos)
                self.SetSizeWH(-1, newheight)
        elif self.oldPos:
            newpos = wx.Point(self.GetPosition().x + pos.x - self.oldPos.x,
                      self.GetPosition().y + pos.y - self.oldPos.y)
    
            if newpos.y < self.Parent.titleHeight:
                newpos.y = self.Parent.titleHeight
            elif newpos.y + self.Size.y > self.Parent.Size.y + 1:
                newpos.y = self.Parent.Size.y - self.Size.y + 1
            if newpos.x < self.Parent.rulerWidth + 1:
                newpos.x = self.Parent.rulerWidth + 1
            elif newpos.x + self.Size.x > self.Parent.Size.x -1:
                newpos.x = self.Parent.GetSize().x - self.Size.x -1
    
            newpos.y -= (newpos.y - self.Parent.titleHeight) % self.Parent.gridHeight
    
            col = self.Parent.GetCol(self.GetPosition().x + pos.x)
            newpos.x = self.Parent.cols[col][0]
            newwidth = self.Parent.cols[col][1]
    
            self.Move(newpos)
            self.SetSizeWH(newwidth, -1)
        
        t = self.GetEvtTime()
        ty = self.Parent.Parent.GetViewStart()[1]+1
        self.Parent.tooltip.Move((-1, ty))
        self.Parent.tooltip.SetLabel('%02d:%02d - %02d:%02d' 
                                     % (t[0][0], t[0][1], t[1][0], t[1][1]))
        self.Refresh()

    def GetEvtTime(self):
        begin = self.GetPosition().y
        end = self.GetPosition().y + self.Size.y
        return [self.GetTimeFromPos(begin), self.GetTimeFromPos(end)]
    
    def GetTimeFromPos(self, y):
        h = (y-self.Parent.titleHeight) / (self.Parent.gridHeight*2)
        m = 60 * ((y-self.Parent.titleHeight) % (self.Parent.gridHeight*2)) / (self.Parent.gridHeight*2)
        return [h,m]
    
    def GetPosFromTime(self, t):
        y = t[0] * (self.Parent.gridHeight*2) + self.Parent.titleHeight + t[1] * self.Parent.gridHeight / 30
        return y
    
    def SetEvtTime(self):
        top = self.GetPosFromTime([self.startTime.GetHour(),self.startTime.GetMinute()])
        bottom = self.GetPosFromTime([self.endTime.GetHour(),self.endTime.GetMinute()])
        col = 0
        for i in range(len(self.Parent.dates)):
            if self.startTime.IsSameDate(self.Parent.dates[i]):
                col = i
                break
        pos = wx.Point(self.Parent.cols[col][0], top)
        size = wx.Size(self.Parent.cols[col][1], bottom-top)
        self.SetSize(size)
        self.SetPosition(pos)
        
    def OnLeftUp(self, event):
        if self.GetCursor() == wx.CURSOR_SIZENS:
            self.SetCursor(wx.CURSOR_DEFAULT)
        if wx.Window.GetCapture() == self:
            self.ReleaseMouse()
            scrollpos = self.Parent.Parent.GetViewStart()[1]
            currentpos = self.GetPosition().y
            if currentpos < scrollpos and (not self.isResizing or self.resizeFromTop):
                self.Parent.Parent.Scroll(-1, currentpos)
            elif currentpos + self.Size.y > scrollpos + self.Parent.Parent.ClientSize.y:
                self.Parent.Parent.Scroll(-1, currentpos + self.Size.y - self.Parent.Parent.ClientSize.y)
        self.oldPos = None
        self.isResizing = False
        self.resizeOutside = False
        self.Parent.tooltip.Show(False)

class _PanelDays(wx.Panel):
    calevents = None
    dates = []
    cols = []
    panelevts = []
    gridHeight = 15
    rulerWidth = 30
    titleHeight = 20
    gridLineColor = wx.Color(192,192,192)
    titleColor = wx.Color(0, 0, 0)
    
    def __init__(self, parent, calevents):
        wx.Panel.__init__(self, parent)
        self.dates = [wx.DateTime.Now()]
        self.calevents = calevents
        self.SetBackgroundColour(wx.Color(255,255,255))
        self.SetSize((-1, 740))
        self.SetSizeHints(-1, 740)
        
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.Bind(wx.EVT_MOTION, self.OnMotion)
        self.Bind(wx.EVT_SIZE, self.OnSize)

#        self.panelevts.append(_PanelEvt(self))
        
        self.tooltip = wx.StaticText(self, -1, '', pos = (1,1), style=wx.BORDER)
        self.tooltip.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_INFOBK))
        self.tooltip.Show(False)

    def OnPaint(self, event):
        if len(self.dates) == 0: return

        dc = wx.PaintDC(self)
        rect = self.GetClientRect()
        dc.SetPen(wx.Pen(self.gridLineColor))
        dc.DrawRectangleRect(rect)
        lines1,lines2,lines3,scales,scaleCoords,titles,titleCoords = [],[],[],[],[],[],[]
        font = self.GetFont()
        font.SetPointSize(7)
        dc.SetFont(font)
        
        dayWidth = (rect.width-self.rulerWidth) / len(self.dates)
        for i in range(0, 49):
            lines1.append([self.rulerWidth, 
                           2*i*self.gridHeight+self.titleHeight, 
                           rect.width, 
                           2*i*self.gridHeight+self.titleHeight])
            lines2.append([self.rulerWidth, 
                           (2*i+1)*self.gridHeight+self.titleHeight, 
                           rect.width, 
                           (2*i+1)*self.gridHeight+self.titleHeight])
        for i in range(0, len(self.dates)):
            title = self.dates[i].Format('%Y-%m-%d')
            titles.append(title)
            extent = dc.GetTextExtent(title)
            titleCoords.append([dayWidth*i+self.rulerWidth + (dayWidth-extent[0])/2, (self.titleHeight-extent[1])/2])
            lines3.append([dayWidth*i+self.rulerWidth, 0, dayWidth*i+self.rulerWidth, rect.height])
        dc.DrawLineList(lines1, wx.Pen(self.gridLineColor))
        dc.DrawLineList(lines2, wx.Pen(self.gridLineColor, style=wx.DOT))
        dc.DrawLineList(lines3, wx.Pen(self.gridLineColor))
        
        for i in range(0, 24):
            scales.append(str(i).rjust(2, '0')+':00')
            scaleCoords.append([4, 2*i*self.gridHeight + self.titleHeight - 5])
        dc.DrawTextList(scales, scaleCoords, self.gridLineColor)

        font.SetPointSize(9)
        dc.SetFont(font)
        dc.DrawTextList(titles, titleCoords, self.titleColor)

    def OnLeftDown(self, event):
        pass

    def OnLeftUp(self, event):
        pass

    def OnMotion(self, event):
        pass
                       
    def OnSize(self, event):
        if len(self.dates) == 0: return
        self.GetCols()
        
    def GetCols(self):
        if len(self.dates) == 0: return
        self.cols = []
        dayWidth = (self.ClientSize.x-self.rulerWidth) / len(self.dates)
        start = self.rulerWidth + 1
        for i in range(len(self.dates)-1):
            self.cols.append([start, dayWidth-1])
            start += dayWidth
        self.cols.append([start, self.ClientSize.x-self.rulerWidth-(len(self.dates)-1)*dayWidth-2])
    
    def GetCol(self, x):
        for i in range(len(self.cols)):
            if i == len(self.cols) - 1:
                if x >= self.cols[i][0]:
                    return i
            else:
                if x >= self.cols[i][0] and x <= self.cols[i][0] + self.cols[i][1]:
                    return i
        if x < self.cols[0][0]: return 0
        elif x > self.cols[len(self.cols)-1][0] + self.cols[len(self.cols)-1][0]:
            return len(self.cols)-1

    def OnEraseBackground(self, event):
        pass

    def SetDates(self, dates):
        self.dates = dates
        self.GetCols()
        self.ShowCalevents()
        self.Refresh()

    def ShowCalevents(self):
        for pnlevt in self.panelevts:
            print pnlevt
            pnlevt.Close()
        if self.calevents.has_key(self.dates[0].Format('%Y-%m-%d')):
            for an_event in self.calevents[self.dates[0].Format('%Y-%m-%d')]:
                pnlevt = _PanelEvt(self, an_event)
                self.panelevts.append(pnlevt)
    
if __name__ == '__main__':
    app = wx.PySimpleApp()
    form = wx.Frame(None)
    PanelDays(form)
    form.Center()
    form.Show()
    app.MainLoop()
